﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameEngine.Entities;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using GameEngine.Camera;
using GameEngine.Managers.IManagers;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;

namespace GameEngine.Scenes
{
    public abstract class Scene
    {
        #region Fields

        protected Texture2D collisionMap;
        protected Texture2D deathTrapMap;
        protected List<Scene> children;
        public bool isActive = true;
        protected List<Layer2D> layers;
        public Texture2D background;
        protected ScrollingBackground scrollingBackground;
        protected Game game;
        public string backgroundSound = "";

        #endregion
        #region Properties

        public Texture2D Background
        {
            get { return background; }
            set { background = value; }
        }

        public virtual Texture2D CollisionMap
        {
            get { return collisionMap; }
            set { collisionMap = value; }
        }

        public virtual Texture2D DeathTrapMap
        {
            get { return deathTrapMap; }
            set { deathTrapMap = value; }
        }

        public virtual List<Layer2D> Layers
        {
            get { return layers; }
            set { layers = value; }
        }

        public ScrollingBackground ScrollingBackground
        {
            get { return scrollingBackground; }
            set { scrollingBackground = value; }
        }

        #endregion

        public Scene(Game game)
        {
            layers = new List<Layer2D>();
            this.game = game;
        }
        
        public virtual List<AbstractEntity> GetSceneObjects()
        {
            List<AbstractEntity> sceneObjects = new List<AbstractEntity>();
            foreach (Layer2D layer in layers)
            {
                sceneObjects.AddRange(layer.GetSceneObjects());
            }
            return sceneObjects;
        }

        public void AddLayer(Layer2D layer)
        {
            layers.Add(layer);
        }


        public virtual void PlayBackgroundSound()
        {
            if (backgroundSound == "" || backgroundSound == null)
                return;

            try
            {
                if (((IAudioManager)game.Services.GetService(typeof(IAudioManager))).GetSoundEffect(backgroundSound) == null)
                {
                    SoundEffect soundEffect = game.Content.Load<SoundEffect>(backgroundSound);
                    ((IAudioManager)game.Services.GetService(typeof(IAudioManager))).AddSoundEffect(soundEffect, backgroundSound);
                    ((IAudioManager)game.Services.GetService(typeof(IAudioManager))).PlayLoopedSound(backgroundSound, 1.0f);
                }
                else
                {
                    ((IAudioManager)game.Services.GetService(typeof(IAudioManager))).PlayLoopedSound(backgroundSound, 1.0f);
                }
            }
            catch (ContentLoadException)
            {
                Console.Write("Exception loading " + backgroundSound + " probably incorrect format\n");
                return;
            }
            catch (Exception)
            {
                Console.Write("Got an exception trying to load background sound " + backgroundSound + "\n");
                return;
            }

        }

        public Texture2D GetBackground()
        {
            return background;
        }


        public void SetBackgroundLayer(Texture2D background, int layer)
        {
            while (layers.Count <= layer)
            {
                layers.Add(new Layer2D(this.game));
            }
            layers.ElementAt(layer).Background = background;
        }

        public void AddEntityToLayer(AbstractEntity entity, int layer)
        {
            while (layers.Count <= layer)
            {
                layers.Add(new Layer2D(this.game));
            }
            layers.ElementAt(layer).SceneObjects.Add(entity);
        }

        public virtual void CheckInput()
        {
            IInputManager input = (IInputManager)game.Services.GetService(typeof(IInputManager));
            if (input.IsStartPressed())
                PauseAction();
            if (input.IsBackPressed())
                BackAction();
        }

        public virtual void PauseAction()
        {
            Console.Write("PauseAction not defined in current scnene");
            //ISceneManager scene = (ISceneManager)game.Services.GetService(typeof(ISceneManager));
            //scene.PushScene(((IResourceManager)game.Services.GetService(typeof(IResourceManager))).GetPauseScene());
        }
        public virtual void BackAction()
        {
            Console.Write("BackAction not defined in current scnene");
            //ISceneManager scene = (ISceneManager)game.Services.GetService(typeof(ISceneManager));
            //scene.PushScene(((IResourceManager)game.Services.GetService(typeof(IResourceManager))).GetPauseScene());
        }

        public virtual void Update(GameTime gameTime)
        {
            if (scrollingBackground != null)
                scrollingBackground.Update(1);

            List<AbstractEntity> entities = this.GetSceneObjects();
            foreach (AbstractEntity entity in entities)
            {
                entity.Update(gameTime);
            }

            CheckInput();
        }

        public virtual void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            spriteBatch.Begin(SpriteSortMode.BackToFront,
                        BlendState.AlphaBlend,
                        null,
                        null,
                        null,
                        null,
                        ((Camera2D)game.Services.GetService(typeof(Camera2D))).GetTransformation());

            if (scrollingBackground != null)
                scrollingBackground.Draw(spriteBatch);
            //if (deathTrapMap != null)
            //    spriteBatch.Draw(deathTrapMap, new Rectangle(0, 0, deathTrapMap.Width, deathTrapMap.Height), Color.White);

            spriteBatch.End();
        }
    }
}
